package cn.redragon.soa.security.keycloak;

import cn.redragon.soa.common.core.constant.AuthConstant;
import cn.redragon.soa.common.core.util.JsonUtil;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.keycloak.representations.AccessToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;

@Slf4j
public class JwtHelper {

    public static Set<? extends GrantedAuthority> extractResourceRoles(Jwt jwt, String keycloakResource) {
        Map<String, AccessToken.Access> resourceAccess = JsonUtil.jsonToObjMap(JsonUtil.objectToJsonStr(jwt.getClaim(AuthConstant.CLAIM_ROLE)),
                                                                               AccessToken.Access.class);
        Set<SimpleGrantedAuthority> clientAuthorities = Optional.ofNullable(resourceAccess)
            .map(resource -> resource.get(keycloakResource))
            .map(AccessToken.Access::getRoles)
            .stream().flatMap(Collection::stream)
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toSet());

        try {
            Map<String, Object> realmMap = jwt.getClaimAsMap(AuthConstant.CLAIM_REALM_ROLE);
            if (MapUtils.isNotEmpty(realmMap)) {
                List<String> realmRoles = JsonUtil.jsonToObjList(JsonUtil.objectToJsonStr(realmMap.get(AuthConstant.CLAIM_WRAPPED_ROLES)), String.class);
                Set<SimpleGrantedAuthority> realmAuthorities = realmRoles.stream().map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toSet());
                clientAuthorities.addAll(realmAuthorities);
            }
        } catch (Exception e) {
            log.error("Parse realm roles failed");
        }

        return clientAuthorities;
    }
}
